package sampleuiplugin;

import gamefw.framework.Coordinate;
import gamefw.framework.Move;
import gamefw.gameplugin.ISpecialEventListener;
import gamefw.uiplugin.IInputManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SampleInputManager implements IInputManager {
	
	private BufferedReader reader;
	
	private Set<ISpecialEventListener> listeners;
	
	private Pattern positionPattern;
	
	private Pattern movePattern;
	
	public SampleInputManager() {
		this.listeners = new HashSet<ISpecialEventListener>();
		
		this.positionPattern = Pattern.compile("^\\((\\d)+, (\\d+)\\)$");
		this.movePattern = Pattern.compile("^\\((\\d)+, (\\d+)\\), \\((\\d)+, (\\d+)\\)$");
		
		this.reader = new BufferedReader(new InputStreamReader(System.in));
	}

	@Override
	public void getStartSignal() {
		System.out.println();
		System.out.println("Press ENTER to start the game.");
		readLine();	// accept anything except "quit"
	}
	
	private String readLine() {
		System.out.print("(Input \"quit\" to exit) >> ");
		String line = "";
		try {
			line = this.reader.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		if (line.equalsIgnoreCase("quit")) {
			for (ISpecialEventListener listener : this.listeners) {
				listener.onQuit();
			}
		}
		
		return line;
	}
	
	private int readInteger() {
		while (true) {
			String line = readLine();
			try {
				int value = Integer.parseInt(line);
				return value;
			} catch (NumberFormatException e) {
				System.out.println("Please input an integer value.");
			}
		}
	}
	
	private int readIntegerInRange(int min, int max) {
		while (true) {
			int value = readInteger();
			if (value < min || value > max) {
				System.out.println("Please input between " + min + " and " + max + ".");
				continue;
			}
			
			return value;
		}
	}

	@Override
	public boolean getPlayerRole(int playerIndex) {
		System.out.println();
		System.out.println("Who will play Player" + playerIndex + "?");
		System.out.println("1) Human\t2) Computer");
		int value = readIntegerInRange(1, 2);
		
		return value == 1;
	}

	@Override
	public Coordinate getPosition() {
		while (true) {
			System.out.println();
			System.out.println("Select a position on the board in \"(x, y)\" format");
			String line = readLine();
			
			Matcher matcher = this.positionPattern.matcher(line);
			if (!matcher.matches()) {
				continue;
			}
			
			return new Coordinate(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)));
		}
	}

	@Override
	public Move getMove() {
		while (true) {
			System.out.println();
			System.out.println("Make a move on the board in \"(x1, y2), (x2, y2)\" format");
			String line = readLine();
			
			Matcher matcher = this.movePattern.matcher(line);
			if (!matcher.matches()) {
				continue;
			}
			
			return new Move(
					new Coordinate(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2))),
					new Coordinate(Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4))));
		}
	}

	@Override
	public void registerSpecialEventListener(ISpecialEventListener listener) {
		this.listeners.add(listener);
	}
}
